package com.he.fetch.test;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.LogFactoryImpl;

import com.he.fetch.test.model.Account;
import com.he.fetch.test.model.AccountType;
import com.he.fetch.test.model.Role;
import com.he.fetch.test.model.Txn;
import com.he.fetch.test.model.User;

public class Load {

    private static final String[] ACCOUNT_TYPE_NAMES = { "personal",
	    "business", "non-profit" };

    private static final Log LOG = LogFactoryImpl.getLog(Load.class);
    private static final String PERSISTENCE_UNIT_NAME = "local";

    private static final String ROLE_NAME_MANAGER = "manager";

    private static void addTxns(Account account, int count) {
	for (int i = 0; i < count; i++) {
	    Txn txn = new Txn();
	    txn.setAmount(DataHelper.randomDouble(100));
	    txn.setDate(new Date());
	    txn.setDescription(DataHelper.randomString(50));
	    account.add(txn);
	}
    }

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

	try {
	    EntityManagerFactory factory = Persistence
		    .createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
	    EntityManager em = factory.createEntityManager();
	    long count = 0;
	    // account type
	    count = em
		    .createQuery(
			    "SELECT o FROM "
				    + AccountType.class.getSimpleName() + " o")
		    .getResultList().size();
	    if (count == 0) {
		LOG.info("adding " + AccountType.class.getSimpleName());
		em.getTransaction().begin();
		for (int i = 0; i < ACCOUNT_TYPE_NAMES.length; i++) {
		    AccountType accountType = new AccountType();
		    accountType.setName(ACCOUNT_TYPE_NAMES[i]);
		    em.persist(accountType);
		}
		em.getTransaction().commit();
	    } else {
		LOG.info(count + " " + AccountType.class.getSimpleName()
			+ "s are present");
	    }

	    // manager Role
	    count = (Long) em.createQuery(
		    "SELECT COUNT(o) FROM " + Role.class.getSimpleName()
			    + " o WHERE o.name = :name").setParameter("name",
		    ROLE_NAME_MANAGER).getSingleResult();

	    Role manager = null;
	    if (count == 0) {
		System.out.println("adding manager"
			+ Role.class.getSimpleName());
		em.getTransaction().begin();
		manager = new Role();
		manager.setName("manager");
		manager.setDescription("manages accounts (also can backup)");
		manager = em.merge(manager);
		em.getTransaction().commit();
	    } else {
		manager = (Role) em.createQuery(
			"SELECT o FROM " + Role.class.getSimpleName()
				+ " o WHERE o.name = :name").setParameter(
			"name", ROLE_NAME_MANAGER).getSingleResult();
		LOG.info(Role.class.getSimpleName() + " " + ROLE_NAME_MANAGER
			+ " is present");
	    }

	    // Users
	    count = (Long) em.createQuery(
		    "SELECT COUNT(o) FROM " + User.class.getSimpleName()
			    + " o LEFT JOIN o.roles r WHERE r = :role")
		    .setParameter("role", manager).getSingleResult();
	    LOG.info("there are " + count + " Users that are managers");
	    if (count == 0) {
		List<User> users = em.createQuery(
			"SELECT o FROM " + User.class.getSimpleName() + " o")
			.setMaxResults(10).getResultList();
		LOG.info("selected " + users.size()
			+ " Users to make some managers");
		if (users.size() < 10) {
		    em.getTransaction().begin();
		    while (users.size() < 10) {
			User user = new User();
			user.setName("load: " + DataHelper.randomString(20));
			user.setPassword(DataHelper.randomString(8));
			users.add(em.merge(user));
		    }
		    em.getTransaction().commit();
		} else {
		    LOG
			    .info("there are "
				    + users.size()
				    + " Users. Not adding any more - but will make some managers");
		}
		em.getTransaction().begin();
		for (User user : users) {
		    user.add(manager);
		    em.merge(user);
		}
		em.getTransaction().commit();
	    }

	    // Account
	    count = (Long) em.createQuery(
		    "SELECT COUNT(o) FROM " + Account.class.getSimpleName()
			    + " o WHERE o.backup IS NULL").getSingleResult();
	    LOG.info("there are " + count + " Accounts with NULL backup");
	    if (count < 10) {
		em.getTransaction().begin();
		for (int i = 0; i < 25; i++) {
		    Account account = new Account();
		    account
			    .setBackup((DataHelper.randomBoolean() ? (User) DataHelper
				    .random(em, User.class, 100)
				    : null));
		    account.setManager((User) DataHelper.random(em, User.class,
			    100));
		    account.setName("load: " + DataHelper.randomString(26));
		    account.setPrimary(DataHelper.randomBoolean());
		    addTxns(account, DataHelper.randomInt(100));
		    account.setType((AccountType) DataHelper.random(em,
			    AccountType.class, 3));
		    em.persist(account);
		}
		em.getTransaction().commit();
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	}

    }

}
